#Import Modules
import os, pygame, math
from pygame.locals import *

# Load up the parent and constituent calsses
from Character import Character
from Projectile import Projectile
from Spikeball import Spikeball
#from Ball import ExplodingBalloon
#from Jumper import MusicalJumper

# Load up our helper functions
from Loaders import *

class DeadPlayer(Projectile):
    """this object contains the ball character"""
    def __init__(self, spawnpoint, x=1):
        Projectile.__init__(self, spawnpoint,(False,False)) #call Projectile initializer
        
        self.frames = list()
        self.frames.append(list())
        self.frames.append(list())
        
        self.frames[0].append(load_frame(os.path.join('data','characters','player',"player-d-l-0.png")))
        self.frames[0].append(load_frame(os.path.join('data','characters','player',"player-d-l-1.png")))
        self.frames[0].append(load_frame(os.path.join('data','characters','player',"player-d-l-2.png")))
        
        self.frames[1].append(load_frame(os.path.join('data','characters','player',"player-d-r-0.png")))
        self.frames[1].append(load_frame(os.path.join('data','characters','player',"player-d-r-1.png")))
        self.frames[1].append(load_frame(os.path.join('data','characters','player',"player-d-r-2.png")))
        
        # Load the initial image
        self.image, self.rect = load_image(os.path.join('data','characters','player',"player-d-l-0.png"))
        self.x = x
        self.z = 0
        self.anim = 0
        self.animspeed = 4
        
        # Non-default physical properties
        self.friction = 0.1
        self.gravity = 0.3
        self.accelerationy = self.gravity
        self.screeneffect = 2
        
        # Properties for animation, AI, etc...
        # These variables are not referenced outside the class. They are what you make of them.
        self.rotation = 0
        self.scale = 1
    
    def die(self):
        Projectile.die(self)
        self.dead = 1
            
    # Override the hit function so that the projectile doesn't get hurt or deflected.
    def hit(self, damage, stun=20, direction=-1, knockback=10): pass
    
    def update(self):
        # This method runs once per frame. Use it for control/AI, animation, and sound effects 
        if self.anim < self.animspeed:
            self.anim += 1
        else:
            self.anim = 0
            if self.z < len(self.frames[self.x])-1:
                self.z += 1
            else:
                self.z = 0
            
        self.image = self.frames[self.x][self.z]
        
        if self.rotation < (math.pi * 2):
            self.rotation += 0.05
        else:
            self.rotation = 0
        
        self.image = pygame.transform.rotate(self.image, math.degrees(self.rotation))
        
        Projectile.update(self)

class Player(Character):
    """this object contains the player character"""
    def __init__(self, spawnpoint, controller):
        Character.__init__(self,spawnpoint,controller) #call Sprite initializer
        
        # Initial image
        self.image, self.rect = load_image(os.path.join('data','characters','player',"player-s-r-0.png"))
        
        # Number of pixels on both sides of the image that do not collide
        self.padx = -92
        self.pady = -60
        
        # Some non-standard variables
        self.maxhealth = 255
        self.health = 255
        self.invincibleframes = 40
        self.name = "PLAYER"
        
        # Some internal vars used for the attack state machine
        self.attacklength = 0
        self.attack = None
        
        # Animation frames
        # Frames is a 3 tier list
        # self.frames[x][y][z]
        # x is the facing direction. 1=left, 0=right
        # y is the action animation. 0=standing, 1=walking, 2=jumping, 3=falling (more to come)
        # z is the current animation step. All animations have at least 3 frames.
        
        self.x = 1
        self.y = 0
        self.z = 0
        self.frameskip = 0  # frameskip is a frame counter to make sure z doesn't change too quickly.
        self.subz = 0       # subz is a state machine because z does not update sequentially
        
        self.blank = pygame.Surface((1,1)).convert_alpha()
        self.blank.fill((255,255,255,0))
        self.frames = list()
        self.frames.append(list())
        self.frames.append(list())
        self.frames[0].append(list())
        self.frames[0].append(list())
        self.frames[0].append(list())
        self.frames[0].append(list())
        self.frames[0].append(list())
        self.frames[1].append(list())
        self.frames[1].append(list())
        self.frames[1].append(list())
        self.frames[1].append(list())
        self.frames[1].append(list())
        
        self.frames[0][0].append(load_frame(os.path.join('data','characters','player',"player-s-l-0.png")))
        self.frames[0][0].append(load_frame(os.path.join('data','characters','player',"player-s-l-1.png")))
        self.frames[0][0].append(load_frame(os.path.join('data','characters','player',"player-s-l-2.png")))
        
        self.frames[1][0].append(load_frame(os.path.join('data','characters','player',"player-s-r-0.png")))
        self.frames[1][0].append(load_frame(os.path.join('data','characters','player',"player-s-r-1.png")))
        self.frames[1][0].append(load_frame(os.path.join('data','characters','player',"player-s-r-2.png")))
        
        self.frames[0][1].append(load_frame(os.path.join('data','characters','player',"player-w-r-0.png")))
        self.frames[1][1].append(load_frame(os.path.join('data','characters','player',"player-w-r-0.png")))
        
        self.frames[0][2].append(load_frame(os.path.join('data','characters','player',"player-j-l-0.png")))
        self.frames[0][2].append(load_frame(os.path.join('data','characters','player',"player-j-l-1.png")))
        self.frames[0][2].append(load_frame(os.path.join('data','characters','player',"player-j-l-2.png")))
        
        self.frames[1][2].append(load_frame(os.path.join('data','characters','player',"player-j-r-0.png")))
        self.frames[1][2].append(load_frame(os.path.join('data','characters','player',"player-j-r-1.png")))
        self.frames[1][2].append(load_frame(os.path.join('data','characters','player',"player-j-r-2.png")))
        
        self.frames[0][4].append(load_frame(os.path.join('data','characters','player',"player-p-l-0.png")))
        self.frames[0][4].append(load_frame(os.path.join('data','characters','player',"player-p-l-1.png")))
        self.frames[0][4].append(load_frame(os.path.join('data','characters','player',"player-p-l-2.png")))
        
        self.frames[1][4].append(load_frame(os.path.join('data','characters','player',"player-p-r-0.png")))
        self.frames[1][4].append(load_frame(os.path.join('data','characters','player',"player-p-r-1.png")))
        self.frames[1][4].append(load_frame(os.path.join('data','characters','player',"player-p-r-2.png")))
        
        # SFX
        self.sfx = list()
        self.sfx.append(load_sound("jump.wav"))
        self.sfx.append(load_sound("playerhit.wav"))
        self.sfx.append(load_sound("death.wav"))
        self.sfx[0].set_volume(0.5)
        
    def hit(self, damage, stun=20, direction=-1, knockback=10):
        if Character.hit(self,damage,stun,direction,knockback):
            self.sfx[1].play()
    
    def die(self):
        if Character.die(self):
            # Release all children
            self.spawner.releasechildren()
            # Spawn the dead shell of the player
            self.spawner.addchild(DeadPlayer((35,20),self.x),1)
            self.sfx[2].play()
            return True
        return False
        
    def update(self):

        Character.update(self)
        
        if self.stun == 0 and self.attacklength == 0 and self.dying == 0:
            if self.controller.punch_low_press == 1:
                self.attack = (10,Rect(10+(self.x * 50),60,50,20))
                self.attackboxes.append(self.attack)
                self.attacklength = 25
                self.y = 4
            if self.controller.punch_high_press == 1:
                self.attack = (10,Rect(45,0,30,50))
                self.attackboxes.append(self.attack)
                self.attacklength = 25
                #self.y = 4
            if self.controller.kick_high_press == 1:
                # I removed the kick and replaced it with a spikeball spawn.
                #self.attack = (10,Rect(10+(self.x * 50),90,30,30))
                #self.attackboxes.append(self.attack)
                self.attacklength = 25
                # This is just here to demo
                if self.controller.up == 1:
                    self.groundy -= 10
                if self.controller.down == 1:
                    self.groundy += 10
                self.spawner.addchild(Spikeball((30,0)), 2)
            if self.controller.kick_low_press == 1 and self.walk == 0:
                self.attack = (10,Rect(45,90,30,50))
                self.attackboxes.append(self.attack)
                self.attacklength = 25
                self.jumpframes = self.maxjumpframes
                self.speedy += 15
                self.y = 2
            
        if self.attacklength == 1 and self.attack != None:
            self.attackboxes.remove(self.attack)
            self.attack = None
        if self.attacklength > 0:
            self.attacklength -= 1
        
        # This method runs once per frame. Use it for updating animation, special control bits and sound effects 
        
        # Check to see if we just started a jump. If so, play the sound, update the activity.
        if self.jumpframes == 1:
            self.sfx[0].play()
            
        if self.jump == 1 and self.speedy < 0 and self.attacklength == 0:
            self.y = 2
        elif self.attacklength == 0:
            self.y = 0
            
        # Update animation frame.
        if self.frameskip == 10:
            self.frameskip = 0
            if self.subz == 3:
                self.subz = 0
            else:
                self.subz = self.subz+1
        else:
            self.frameskip = self.frameskip+1
        
        if self.subz == 0:
            self.z=0
        elif self.subz == 1:
            self.z=1
        elif self.subz == 2:
            self.z=2
        elif self.subz == 3:
            self.z=1
        
        if self.walk == 1 and self.attacklength == 0:
            if self.thrustx > 0:
                self.x = 1
            elif self.thrustx < 0:
                self.x = 0
        
        if self.dying == 0:
            self.image = self.frames[self.x][self.y][self.z]
        else:
            self.image = self.blank
        
        if self.dying == 1 and not(self.spawner.haschildren()):
            self.dead = 1